#include "TcpConnector.h"

namespace myrpc {
namespace mynet {
int TcpConnector::Connect(std::string ip, int port) {
  ip_ = ip;
  port_ = port;
  loop_ = uvw::Loop::getDefault();
  _tcphandler = loop_->resource<uvw::TcpHandle>();
  _tcphandler->on<uvw::ErrorEvent>(
      [&](const uvw::ErrorEvent &err, uvw::TcpHandle &) {
        // this->errorhandle_(shared_from_this());
        std::cout << err.what();
      });

  _tcphandler->on<uvw::WriteEvent>(
      [&](const uvw::WriteEvent &, uvw::TcpHandle &handle) {
        std::cout << "WriteEvent \r\n";		
      });

  _tcphandler->on<uvw::ConnectEvent>(
      [&](const uvw::ConnectEvent &event, uvw::TcpHandle &handle) {
	    _tcphandler->read();
        std::cout << "ConnectEvent";
      });

  _tcphandler->on<uvw::CloseEvent>(
      [&](const uvw::CloseEvent &, uvw::TcpHandle &) {
        this->closehandle_(shared_from_this());
      });

  _tcphandler->on<uvw::DataEvent>(
      [=](const uvw::DataEvent &event, uvw::TcpHandle &handle) { 

        const char *start = nullptr;
        const char *per = nullptr;
        start = event.data.get();
        int bodylenght = event.length;
        per = start;
        do {
          if (bodylenght_ == 0) {
            myrpc::Header header;
            bool b = header.ParseFromArray(per, 5);
            bodylenght_ = header.len();
            per = per + 5;
            bodylenght = bodylenght - 5;
            if (bodylenght_ <= bodylenght) {
              myrpc::Response request;
              request.ParseFromArray(per, bodylenght_);
              bodylenght = bodylenght - bodylenght_;
              per = per + bodylenght_;
              std::shared_ptr<ClientPackage> pack(new ClientPackage);
              pack->body = request;
              pack->connect = this->shared_from_this();
              bodylenght_ = 0;
              this->packgereachhandle_(pack);
              if (bodylenght == 0) {
                break;
              }
            } else {
              in_ = std::string(per);
              bodylenght_ = bodylenght_ - bodylenght;
            }
          } else {
            if (bodylenght_ <= bodylenght) {
              myrpc::Response request;
              char *buf = new char[bodylenght_ + 1];
              memset(buf, '\0', bodylenght_ + 1);
              memcpy(buf, per, bodylenght_);
              in_.append(buf);
              request.ParseFromString(in_);
              bodylenght = bodylenght - bodylenght_;
              per = per + bodylenght_;
              std::shared_ptr<ClientPackage> pack(new ClientPackage);
              pack->body = request;
              pack->connect = shared_from_this();
              bodylenght_ = 0;
              this->packgereachhandle_(pack);
              if (bodylenght == 0) {
                break;
              }
            } else {
              in_ = std::string(per);
              bodylenght_ = bodylenght_ - bodylenght;
            }
          }
        } while (true);
      });

  _tcphandler->connect(ip_, port_);
  loop_->run();
  return 0;
}
void TcpConnector::Send(std::string data, int len) {
  _tcphandler->write(const_cast<char *>(data.c_str()), len);
  loop_->run<uvw::Loop::Mode::ONCE>();
}
}
}
